package org.jeecg.modules.login.handler.ding;

import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.OapiGettokenRequest;
import com.dingtalk.api.request.OapiUserGetuserinfoRequest;
import com.dingtalk.api.request.OapiV2UserGetRequest;
import com.dingtalk.api.response.OapiGettokenResponse;
import com.dingtalk.api.response.OapiUserGetuserinfoResponse;
import com.dingtalk.api.response.OapiV2UserGetResponse;
import com.taobao.api.ApiException;
import lombok.Data;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;

/**
 * 钉钉小程序执行器
 *
 * @author tianyi.jiang
 * @since 1.0.0
 */
@Slf4j
@Component
@ConditionalOnExpression("'${basicplatform.ding.mini-program.enable:false}'.equals('true')")
public class DingMiniProgramHandler {

    private final DingMiniProgramProperty dingMiniProgramProperty;

    /**
     * [Ding Ding] 小程序免密登录(授权码获取用户信息)
     *
     * @param code 授权码
     * @return OapiV2UserGetResponse {@link OapiV2UserGetResponse}
     * @throws ApiException e {@link ApiException}
     */
    public OapiV2UserGetResponse passwordFree(String code) throws ApiException {
        // 获取access_token
        String accessToken = dingMiniProgramProperty.accessToken();
        // 获取用户信息
        DingTalkClient client4UserId = new DefaultDingTalkClient("https://oapi.dingtalk.com/user/getuserinfo");
        OapiUserGetuserinfoRequest request = new OapiUserGetuserinfoRequest();
        request.setCode(code);
        request.setHttpMethod(HttpMethod.GET.name());
        OapiUserGetuserinfoResponse response = client4UserId.execute(request, accessToken);
        // 查询得到当前用户的userId
        // 获得到userId之后应用应该处理应用自身的登录会话管理（session）,避免后续的业务交互（前端到应用服务端）每次都要重新获取用户身份，提升用户体验
        String userId = response.getUserid();
        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/user/get");
        OapiV2UserGetRequest req = new OapiV2UserGetRequest();
        req.setUserid(userId);
        req.setLanguage("zh_CN");
        return client.execute(req, accessToken);
    }

    public DingMiniProgramHandler(DingMiniProgramProperty dingMiniProgramProperty) {
        this.dingMiniProgramProperty = dingMiniProgramProperty;
    }

    @Slf4j
    @Data
    @Configuration
    @ConfigurationProperties(prefix = "basicplatform.ding.mini-program")
    public static class DingMiniProgramProperty {
        /**
         * 认证Key
         */
        private String appKey;
        /**
         * 认证秘钥
         */
        private String appSecret;
        /**
         * 应用Id
         */
        private Long agentId;

        /**
         * 获取令牌
         *
         * @return access token
         */
        @SneakyThrows
        protected String accessToken() {
            OapiGettokenRequest oapiGettokenRequest = new OapiGettokenRequest();
            oapiGettokenRequest.setAppkey(this.getAppKey());
            oapiGettokenRequest.setAppsecret(this.getAppSecret());
            oapiGettokenRequest.setHttpMethod(HttpMethod.GET.name());
            DingTalkClient dingTalkClient = new DefaultDingTalkClient("https://oapi.dingtalk.com/gettoken");
            OapiGettokenResponse oapiGettokenResponse = dingTalkClient.execute(oapiGettokenRequest);
            log.info("[DING DING] Access token api response: {}", oapiGettokenResponse.toString());
            return oapiGettokenResponse.getAccessToken();
        }
    }
}
